package buzzTest;

import inputs.Color;
import inputs.Constant;
import inputs.Input;

import java.util.ArrayList;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Receiver;
import javax.sound.midi.MidiDevice.Info;

import midi.PitchVelocityMidiOutParameter;
import outputAdapters.MiddleAdapter;
import outputAdapters.OutputAdapter;
import outputAdapters.OutputRanges;
import outputAdapters.ScaleAdapter;
import outputAdapters.SimpleRange;
import codeanticode.gsvideo.GSCapture;
import codeanticode.gsvideo.GSMovie;
import dataModifiers.Average;
import dataModifiers.HighPass;
import dataModifiers.Modifier;
import dataModifiers.Sum;
import processing.core.PApplet;
import processing.core.PFont;

public class BuzzDemoTrackAndSampleVideoLoopComplex extends PApplet{
	GSMovie myMovie;
	GSCapture cam; // Capture object
	int vidX = 640, vidY = 480; // Size of the applet window and capture
	int redVal, greenVal, blueVal; // Variables to hold the value of each color
	int colorVal, totalVal, adaptedVal; // Hold the total color value
	PFont font; // Font to write on the screen with
	Color redColor;
	Color blueColor;
	Color greenColor;
	Modifier rbSumMod, rgbSumMod, totalHighPass, rgbAvgMod;
	OutputAdapter rbSumPitchScaleAdapter, rgbSumPitchScaleAdapter, rgbAvgPitchScaleAdapter, rgbAvgVelScaleAdapter;
	OutputAdapter totalHighPassPitchScaleAdapter, totalHighPassVelScaleAdapter;
	PitchVelocityMidiOutParameter dronePitchOut, arpPitchOut, harmPitchOut;
	
	public void setup() {
		// Initialize the applet window
		size(vidX, vidY);
		background(0);
		fill(255);
		stroke(255);
		
		// Load and set the font
		font = loadFont("CourierNew36.vlw");
		textFont(font, 32);
		
		frameRate(30);
		
		// Initialize the capture device
		cam = new GSCapture(this, vidX, vidY);
		
		
		redColor = new Color(0);
		blueColor = new Color(0);
		greenColor = new Color(0);
		ArrayList<Input> rbList = new ArrayList<Input>(2);
		rbList.add(redColor);
		rbList.add(blueColor);
		rbSumMod = new Sum(rbList);
		rbSumMod.setRun(false);
		
		ArrayList<Input> rgbList = new ArrayList<Input>(3);
		rgbList.add(redColor);
		rgbList.add(greenColor);
		rgbList.add(blueColor);
		rgbSumMod = new Sum(rgbList);
		rgbAvgMod = new Average(rgbList);
		rgbAvgMod.setRun(false);
		
		ArrayList<Input> totalHighPassList = new ArrayList<Input>(2);
		totalHighPassList.add(new Constant(150));
		totalHighPassList.add(rgbSumMod);
		totalHighPass = new HighPass(totalHighPassList);
		
		
		Info[] infos = MidiSystem.getMidiDeviceInfo();
		int i;
		for (i = 0; i < infos.length; i++){
			
			System.out.println(infos[i]);
			
			if (infos[i].toString().contains("Out To MIDI Yoke:  1"))
			{
				break;
			}
		}
		
		try{
			MidiDevice MidiYoke = MidiSystem.getMidiDevice(infos[i]);
		
			MidiYoke.open();
			Receiver rec = MidiYoke.getReceiver();
		
			rbSumPitchScaleAdapter = new ScaleAdapter(OutputRanges.Pitch, rbSumMod);
			rgbSumPitchScaleAdapter = new ScaleAdapter(OutputRanges.Pitch, rgbSumMod);
			rgbAvgPitchScaleAdapter = new ScaleAdapter(OutputRanges.Pitch, rgbAvgMod);
			rgbAvgVelScaleAdapter = new ScaleAdapter(new SimpleRange(60, 60), rgbAvgMod);
			totalHighPassPitchScaleAdapter = new ScaleAdapter(OutputRanges.Pitch, totalHighPass);
			totalHighPassVelScaleAdapter = new ScaleAdapter(new SimpleRange(60, 60), totalHighPass);
			dronePitchOut = new PitchVelocityMidiOutParameter(rbSumPitchScaleAdapter, new Constant(60), rec, 1);
			arpPitchOut = new PitchVelocityMidiOutParameter(rgbSumPitchScaleAdapter, totalHighPassVelScaleAdapter, rec, 2);
			harmPitchOut = new PitchVelocityMidiOutParameter(rgbAvgPitchScaleAdapter, rgbAvgVelScaleAdapter, rec, 3);
			
			
			
			
		}
		catch (Exception e)
		{
			System.out.println("Failed to open MIDI");
		}
		
	}

	public void draw(){
		// Grab image from the webcam if possible
		  if (cam.available()) {
		        cam.read();
		        image(cam, 0, 0);
		    }
		  
		//rotate(PI/2);
		// Get the color from the current mouse position
		colorVal = get(mouseX, mouseY);
		
		// Store each color individual
		redVal = (int) red(colorVal);
		greenVal = (int) green(colorVal);
		blueVal = (int) blue(colorVal);
		totalVal = (redVal + greenVal + blueVal) / 3;		
		
		redColor.setValue(redVal);
		blueColor.setValue(blueVal);
		greenColor.setValue(greenVal);
		rbSumMod.UpdateInput();
		rgbSumMod.UpdateInput();
		totalHighPass.UpdateInput();
		rgbAvgMod.UpdateInput();
		
		rbSumPitchScaleAdapter.UpdateInput();
		rgbSumPitchScaleAdapter.UpdateInput();
		rgbAvgPitchScaleAdapter.UpdateInput();
		rgbAvgVelScaleAdapter.UpdateInput();
		totalHighPassPitchScaleAdapter.UpdateInput();
		totalHighPassVelScaleAdapter.UpdateInput();
		
		
		totalVal = rbSumMod.getValue();
		adaptedVal = rbSumPitchScaleAdapter.getValue();
		
			dronePitchOut.Write();
			arpPitchOut.Write();
		//	harmPitchOut.Write();
		
		
		fill(0, 0);
		// Draw a circle by the cursor
		ellipse(mouseX, mouseY, 10, 10);
		
		
		fill (255, 255);
		
		// Draw each color to the applet
		text("R = " + redVal, 5, 30);
		text("G = " + greenVal, 5, 60);
		text("B = " + blueVal, 5, 90);
		text("T = " + totalVal, 5, 120);
		text("D = " + rbSumPitchScaleAdapter.getValue(), 5, 150);
		text("A = " + rgbSumPitchScaleAdapter.getValue(), 5, 180);
		text("H = " + rgbAvgPitchScaleAdapter.getValue(), 5, 210);
		
		
		
		rbSumMod.Invalidate();
		rgbSumMod.Invalidate();
		totalHighPass.Invalidate();
		rgbAvgMod.Invalidate();
		
		rbSumPitchScaleAdapter.Invalidate();
		rgbSumPitchScaleAdapter.Invalidate();
		rgbAvgPitchScaleAdapter.Invalidate();
		rgbAvgVelScaleAdapter.Invalidate();
		totalHighPassPitchScaleAdapter.Invalidate();
		totalHighPassVelScaleAdapter.Invalidate();
	}
	
	
	// Allows the program to be run as a java application.
	public static void main(String args[]){
		PApplet.main(new String[] { "--present", "WebCamColorMidi"});
	}
}
